package com.zzwtec.androidtest;

import androidx.appcompat.app.AppCompatActivity;

import android.content.pm.PackageManager;
import android.opengl.Matrix;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Looper;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import java.io.DataOutputStream;
import java.io.File;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.Map;

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.
    static {
//        System.loadLibrary("native-lib-v1");
    }

    private TextView tv;

    private String assetPath = "so";
    private int libnativeLibVer = 1;
    private String libnativeLibPath;

    private int time = 5;

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        Log.d("Key", "getKeyCode:"+event.getKeyCode()+" getAction:"+event.getAction());
        return super.dispatchKeyEvent(event);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        libnativeLibVer = getSharedPreferences(Common.SO_INFO, MODE_PRIVATE).getInt("libnative-lib", 1);
        libnativeLibPath = getSharedPreferences(Common.SO_INFO, MODE_PRIVATE).getString("libnative-lib-ver", null);

        if(libnativeLibPath == null){
            libnativeLibVer = 1;
//        Common.loadApkSoLib(getApplicationContext(), "native-lib-v"+libnativeLibVer); // 与下面方法效果一样，都是加载同一个so库
            Common.loadApkSoLib(getApplicationContext(), "libnative-lib-v"+libnativeLibVer+".so");
            Log.e(Common.TAG, "\n=======================\nload so [libnative-lib-v"+libnativeLibVer+".so]\n=======================");
        }else{
            Common.loadPathSoLib(libnativeLibPath);
            Log.e(Common.TAG, "\n=======================\nload so ["+libnativeLibPath+"]\n=======================");
        }

        Log.d(Common.TAG, "java.library.path:["+System.getProperty("java.library.path")+"]");
        Log.d(Common.TAG, "getApplicationInfo().nativeLibraryDir:["+getApplicationInfo().nativeLibraryDir+"]");
        Map<String, String> envMap = System.getenv();
        if(envMap!=null && !envMap.isEmpty()){
            Log.d(Common.TAG, "========== env ==========");
            for(Map.Entry<String, String> entry : envMap.entrySet()){
                Log.d(Common.TAG, entry.getKey()+" : "+entry.getValue());
            }
            Log.d(Common.TAG, "=========================");
        }

//        Common.getAllSOLoaded();
        Common.getCurrApkSOLoaded();

        // Example of a call to a native method
        tv = findViewById(R.id.sample_text);
        tv.setText(JniClass.stringFromJNI());

        matrixRotateM();
        matrixScaleM();
        matrixTranslateM();
    }

    /**
     * 切换加载另一个so库，需要重启APP才生效
     * @param view
     */
    public void switchLib(View view){
        // 切换so 需要将本工程的 assets/libnative-lib-v2.so 复制到 getApplicationInfo().dataDir 目录下的so里面，模拟通过网络下载热修复文件
        try{
            libnativeLibVer = libnativeLibVer == 1 ? 2 : 1;
            String pathLib = getApplicationInfo().dataDir + File.separator + assetPath + File.separator+"libnative-lib-v"+libnativeLibVer+".so";

            File file = new File(pathLib);
            if(file.exists()){
                getSharedPreferences(Common.SO_INFO, MODE_PRIVATE)
                        .edit()
                        .putInt("libnative-lib", libnativeLibVer)
                        .apply();
                getSharedPreferences(Common.SO_INFO, MODE_PRIVATE)
                        .edit()
                        .putString("libnative-lib-ver", pathLib)
                        .apply();
                Log.d(Common.TAG, "c:[" +pathLib+"] is exist");

                showTips();

                Common.loadPathSoLib(pathLib);
                tv.setText(JniClass.stringFromJNI());

                ((Button)view).setText(time+"秒后将退出APP，需要再次手动打开APP");
                ((Button)view).setClickable(false);

                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try{
                            Thread.currentThread().sleep(time * 1000);
                        }catch (Exception e){

                        }
                        finish();
                    }
                }).start();
            }else{
                String sdcardPath = getApplicationInfo().dataDir + File.separator + assetPath;
                FileUtil.copyFilesFromAssets(getApplicationContext(), assetPath, sdcardPath);
                file = new File(pathLib);
                if(file.exists()){
                    Log.d(Common.TAG, "c:[" +pathLib+"] is exist");
                }else {
                    Log.d(Common.TAG, "pathLib:[" +pathLib+"] is not exist");
                }
            }
        }catch (Exception e){
            Log.e(Common.TAG, "loadPathSoLib Exception", e);
        }
    }

    public void test(View view){
        Test.test();
    }

    @Override
    public void finish() {
        super.finish();

        System.exit(0);
    }

    private void showTips() {
        if (Common.isMainThread()) {
            Toast.makeText(getApplicationContext(), time+"秒后将退出APP，需要再次手动打开APP", Toast.LENGTH_LONG);
        }else{
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    showTips();
                }
            });
        }
    }
    
    // 原始矩阵
    private static final float[] ORIGINAL = {
            1, 0, 0, 0,
            0, 1, 0, 0,
            0, 0, 1, 0,
            0, 0, 0, 1
    };
    
    // 旋转矩阵
    public void matrixRotateM() {
        float[] mMatrix = new float[16];

        Matrix.rotateM(mMatrix, 0, ORIGINAL.clone(), 0, 0, 0, 0, 1);
        printf(mMatrix, 4, "RotateM 0 [0, 0, 1]");

        Matrix.rotateM(mMatrix, 0, ORIGINAL.clone(), 0, 90, 0, 0, 1);
        printf(mMatrix, 4, "RotateM 90 [0, 0, 1]");

        Matrix.rotateM(mMatrix, 0, ORIGINAL.clone(), 0, 180, 0, 0, 1);
        printf(mMatrix, 4, "RotateM 180 [0, 0, 1]");

        Matrix.rotateM(mMatrix, 0, ORIGINAL.clone(), 0, 270, 0, 0, 1);
        printf(mMatrix, 4, "RotateM 270 [0, 0, 1]");

        Matrix.rotateM(mMatrix, 0, ORIGINAL.clone(), 0, 0, 1, 1, 1);
        printf(mMatrix, 4, "RotateM 0 [1, 1, 1]");

        Matrix.rotateM(mMatrix, 0, ORIGINAL.clone(), 0, 90, 1, 1, 1);
        printf(mMatrix, 4, "RotateM 90 [1, 1, 1]");

        Matrix.rotateM(mMatrix, 0, ORIGINAL.clone(), 0, 180, 1, 1, 1);
        printf(mMatrix, 4, "RotateM 180 [1, 1, 1]");

        Matrix.rotateM(mMatrix, 0, ORIGINAL.clone(), 0, 270, 1, 1, 1);
        printf(mMatrix, 4, "RotateM 270 [1, 1, 1]");
    }

    // 镜像矩阵
    public void matrixScaleM(){
        float[] mMatrix = new float[16];

        Matrix.scaleM(mMatrix, 0, ORIGINAL.clone(), 0, 1, 1, 1);
        printf(mMatrix, 4, "ScaleM [1, 1, 1]");

        Matrix.scaleM(mMatrix, 0, ORIGINAL.clone(), 0, -1, 1, 1);
        printf(mMatrix, 4, "ScaleM [-1, 1, 1]");

        Matrix.scaleM(mMatrix, 0, ORIGINAL.clone(),  0, 1, -1, 1);
        printf(mMatrix, 4, "ScaleM [1, -1, 1]");

        Matrix.scaleM(mMatrix, 0, ORIGINAL.clone(), 0, 1, 1, -1);
        printf(mMatrix, 4, "ScaleM [1, 1, -1]");
    }

    public void matrixTranslateM(){
        float[] mMatrix = new float[16];

        Matrix.translateM(mMatrix, 0, ORIGINAL.clone(), 0, 0,0,0);
        printf(mMatrix, 4, "TranslateM [0, 0, 0]");

        Matrix.translateM(mMatrix, 0, ORIGINAL.clone(), 0, 1,0,0);
        printf(mMatrix, 4, "TranslateM [1, 0, 0]");

        Matrix.translateM(mMatrix, 0, ORIGINAL.clone(), 0, 0,1,0);
        printf(mMatrix, 4, "TranslateM [0, 1, 0]");

        Matrix.translateM(mMatrix, 0, ORIGINAL.clone(), 0, 0,0,1);
        printf(mMatrix, 4, "TranslateM [0, 0, 1]");
    }


    private void printf(float[] matrix, int numX, String msg){
        System.out.println("------------- "+msg+" ---------");
        StringBuilder sb = new StringBuilder();
        for(int i=0; i< matrix.length; i++){
            sb.append(String.format("\t%4.2f",matrix[i]));
            if((i+1) % numX == 0){
                sb.append("\n");
            }
        }
        System.out.println(sb.toString());
    }
}
